package com.qunar.qcf.proxy;

import java.net.InetSocketAddress;

import com.qunar.qcf.core.future.ConnectFuture;
import com.qunar.qcf.filter.codec.ProtocolCodecFilter;
import com.qunar.qcf.filter.codec.serialization.ObjectSerializationCodecFactory;
import com.qunar.qcf.handler.AbstractClientHandler;
import com.qunar.qcf.handler.IoClientHandler;
import com.qunar.qcf.handler.transport.ClientSender;
import com.qunar.qcf.socket.nio.NioSocketConnector;
import com.qunar.qcf.util.Constants;

/**
 * qcf client
 * 
 * @author zhangwan
 * @email wan.zhang@qunar.com
 * 
 * @param <T>
 */
public final class QCFClient<T> {
	private final NioSocketConnector connector = new NioSocketConnector();
	private AbstractClientHandler handler;
//	private static final QCFClient instance = new QCFClient(IoClientHandler.class);
	
	public static QCFClient createProxy() {
		return new QCFClient(IoClientHandler.class);
	}

	private QCFClient(Class<T> clazz) {
			try {
				handler = (AbstractClientHandler) clazz.newInstance();
				setHandler(handler, connector);
			}  catch (Exception e) {
				//通过构造器创建对象时候抛出的错误
				throw new InstantiationError(e.getMessage());
			}
	}

	private void setHandler(AbstractClientHandler handler, NioSocketConnector connector) {
		this.handler = handler;
		handler.setConnector(connector);
	}

	public AbstractClientHandler getHandler() {
		return this.handler;
	}

	public ClientSender connect(String address, int port) {
		connector.setConnectTimeoutMillis(Constants.CONNECT_TIMEOUT);
		connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ObjectSerializationCodecFactory()));
		
		connector.setHandler(handler);
		ConnectFuture future = connector.connect(new InetSocketAddress(address, port));
		future.awaitUninterruptibly();

		if (!future.isConnected()) {
			throw new IllegalStateException("connected failed.");
		}

		ClientSender sender = new ClientSender(future, connector, handler.ret);
		return sender;
	}

}
